use crate::config::BinanceConfig;
use crate::errors::{BinanceError, Result};
use crate::rest::{MarketApi, AccountApi, TradeApi};
use reqwest::{Client, Proxy};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;

/// REST API客户端
pub struct RestClient {
    config: Arc<BinanceConfig>,
    client: Client,
}

impl RestClient {
    /// 创建新的REST客户端
    pub fn new(config: Arc<BinanceConfig>) -> Result<Self> {
        let mut builder = Client::builder()
            .timeout(Duration::from_secs(config.timeout_seconds));

        // 设置HTTP代理
        if let Some(proxy_url) = &config.http_proxy {
            if let Ok(proxy) = Proxy::all(proxy_url) {
                builder = builder.proxy(proxy);
                tracing::info!("[REST] Using HTTP proxy: {}", proxy_url);
            } else {
                return Err(BinanceError::ConfigError(format!(
                    "Invalid HTTP proxy URL: {}", proxy_url
                )));
            }
        }

        let client = builder.build()
            .map_err(|e| BinanceError::ConfigError(format!("Failed to create HTTP client: {}", e)))?;

        Ok(Self { config, client })
    }

    /// 执行GET请求
    pub async fn get(&self, endpoint: &str, signed: bool) -> Result<String> {
        let url = self.build_url(endpoint, signed).await?;
        
        let request = self.client.get(&url)
            .header("X-MBX-APIKEY", &self.config.api_key);

        let response = request.send().await
            .map_err(|e| BinanceError::NetworkError(format!("GET request failed: {}", e)))?;

        self.handle_response(response).await
    }

    /// 执行POST请求
    pub async fn post(&self, endpoint: &str, params: &HashMap<String, String>, signed: bool) -> Result<String> {
        let url = self.build_url(endpoint, false).await?;
        
        let request = self.client.post(&url)
            .header("X-MBX-APIKEY", &self.config.api_key)
            .header("Content-Type", "application/x-www-form-urlencoded");

        let body = if signed {
            self.build_signed_body(params).await?
        } else {
            self.build_query_string(params)
        };

        let response = request.body(body).send().await
            .map_err(|e| BinanceError::NetworkError(format!("POST request failed: {}", e)))?;

        self.handle_response(response).await
    }

    /// 执行PUT请求
    pub async fn put(&self, endpoint: &str, signed: bool) -> Result<String> {
        let url = self.build_url(endpoint, signed).await?;
        
        let response = self.client.put(&url)
            .header("X-MBX-APIKEY", &self.config.api_key)
            .send().await
            .map_err(|e| BinanceError::NetworkError(format!("PUT request failed: {}", e)))?;

        self.handle_response(response).await
    }

    /// 执行DELETE请求
    pub async fn delete(&self, endpoint: &str, signed: bool) -> Result<String> {
        let url = self.build_url(endpoint, signed).await?;
        
        let response = self.client.delete(&url)
            .header("X-MBX-APIKEY", &self.config.api_key)
            .send().await
            .map_err(|e| BinanceError::NetworkError(format!("DELETE request failed: {}", e)))?;

        self.handle_response(response).await
    }

    /// 构建URL
    async fn build_url(&self, endpoint: &str, signed: bool) -> Result<String> {
        let mut url = if endpoint.starts_with("http") {
            // 如果endpoint已经是完整URL，直接使用
            endpoint.to_string()
        } else if endpoint.starts_with("/") && endpoint.contains("/v") {
            // 如果endpoint包含完整路径（包含版本号），直接构建
            format!("{}{}", self.config.rest_base_url(), endpoint)
        } else {
            // 否则使用默认的rest_url方法
            self.config.rest_url(endpoint)
        };
        
        if signed {
            let timestamp = chrono::Utc::now().timestamp_millis();
            let query = format!("timestamp={}", timestamp);
            let signature = self.sign(&query)?;
            url = format!("{}?{}&signature={}", url, query, signature);
            
            // 调试日志
            tracing::debug!("[REST] 构建签名URL: {}", url);
            tracing::debug!("[REST] 查询字符串: {}", query);
            tracing::debug!("[REST] 签名: {}", signature);
        } else {
            tracing::debug!("[REST] 构建公共URL: {}", url);
        }

        Ok(url)
    }

    /// 构建签名查询字符串
    async fn build_signed_body(&self, params: &HashMap<String, String>) -> Result<String> {
        let mut query_parts = Vec::new();
        
        for (key, value) in params {
            query_parts.push(format!("{}={}", key, value));
        }

        let timestamp = chrono::Utc::now().timestamp_millis();
        query_parts.push(format!("timestamp={}", timestamp));

        let query = query_parts.join("&");
        let signature = self.sign(&query)?;
        
        Ok(format!("{}&signature={}", query, signature))
    }

    /// 构建查询字符串
    fn build_query_string(&self, params: &HashMap<String, String>) -> String {
        params.iter()
            .map(|(k, v)| format!("{}={}", k, v))
            .collect::<Vec<_>>()
            .join("&")
    }

    /// 签名
    fn sign(&self, query: &str) -> Result<String> {
        use hmac::{Hmac, Mac};
        use sha2::Sha256;
        
        type HmacSha256 = Hmac<Sha256>;
        
        let mut mac = HmacSha256::new_from_slice(self.config.secret_key.as_bytes())
            .map_err(|e| BinanceError::ConfigError(format!("HMAC key error: {}", e)))?;
        
        mac.update(query.as_bytes());
        let result = mac.finalize();
        
        Ok(hex::encode(result.into_bytes()))
    }

    /// 处理HTTP响应
    async fn handle_response(&self, response: reqwest::Response) -> Result<String> {
        let status = response.status();
        let text = response.text().await
            .map_err(|e| BinanceError::NetworkError(format!("Failed to read response: {}", e)))?;

        if !status.is_success() {
            // 尝试解析Binance API错误
            if let Ok(api_error) = serde_json::from_str::<crate::models::BinanceApiError>(&text) {
                return Err(BinanceError::ApiError(crate::errors::BinanceApiError {
                    code: api_error.code,
                    msg: api_error.msg,
                }));
            }
            
            return Err(BinanceError::HttpError(status.as_u16(), text));
        }

        Ok(text)
    }

    /// 获取配置
    pub fn config(&self) -> &BinanceConfig {
        &self.config
    }

    /// 构建灵活的API URL
    pub fn build_api_url(&self, endpoint: &str) -> String {
        // 如果endpoint已经包含完整路径（以/开头且包含版本号），直接使用
        if endpoint.starts_with("/") && endpoint.contains("/v") {
            format!("{}{}", self.config.rest_base_url(), endpoint)
        } else {
            // 否则使用默认的rest_url方法
            self.config.rest_url(endpoint)
        }
    }

    /// 获取市场数据API
    pub fn market(&self) -> MarketApi {
        MarketApi::new(self)
    }

    /// 获取账户API
    pub fn account(&self) -> AccountApi {
        AccountApi::new(self)
    }

    /// 获取交易API
    pub fn trade(&self) -> TradeApi {
        TradeApi::new(self)
    }
}
